import { renderDate } from './render.js'
import { rebuild } from './mount.js'
import { getObjectValue } from '../util/ObjectUtil.js'

const arrayPrototype = Array.prototype
/**
*创建对象代理
*@param {Hue} vm 创建的Hue实例
*@param {Object} obj 代理的对象
*@param {string} namespace 命名空间
*@param {boolean} isVmProxy 是否给vm代理，默认为true
*/
function creatObjProxy(vm, obj, namespace, isVmProxy) {
  let objectProxy = {}
  for (const key in obj) {
    let internalValue = obj[key]
    Object.defineProperty(objectProxy, key, {
      configurable: true,
      get() {
        // console.log(getNameSpace(namespace, key))
        return internalValue
      },
      set(val) {
        internalValue = val
        let value = getObjectValue(vm._data, getNameSpace(namespace, key))
        if (value instanceof Array) {
          value = constructProxy(vm, value, getNameSpace(namespace, key))
          rebuild(vm, getNameSpace(namespace, key));
          renderDate(vm, getNameSpace(namespace, key))
        } else {
          renderDate(vm, getNameSpace(namespace, key))
        }
      }
    })
    if (isVmProxy) {
      Object.defineProperty(vm, key, {
        configurable: true,
        get() {
          // console.log(getNameSpace(namespace, key))
          return internalValue
        },
        set(val) {
          internalValue = val
          let value = getObjectValue(vm._data, getNameSpace(namespace, key))
          if (value instanceof Array) {
            value = constructProxy(vm, value, getNameSpace(namespace, key))
            rebuild(vm, getNameSpace(namespace, key));
            renderDate(vm, getNameSpace(namespace, key))
          } else {
            renderDate(vm, getNameSpace(namespace, key))
          }
        }
      })
    }
    // 解决对象(数组)嵌套
    if (internalValue instanceof Object) objectProxy[key] = constructProxy(vm, internalValue, getNameSpace(namespace, key), false)
  }
  return objectProxy
}

/**
*创建数组代理
*@param {Hue} vm 创建的Hue实例
*@param {Array} arr 代理的数组
*@param {string} namespace 命名空间
*/
function creatArrayProxy(vm, arr, namespace) {
  let arr_pro = {
    toString() {
      let result = ''
      for (let i = 0; i < arr.length; i++) {
        result += arr[i] + ' ,'
      }
      return result.substring(0, result.length - 2)
    }
  }
  defArrayFunc.call(vm, vm, 'push', arr_pro, namespace)
  defArrayFunc.call(vm, vm, 'pop', arr_pro, namespace)
  defArrayFunc.call(vm, vm, 'shift', arr_pro, namespace)
  defArrayFunc.call(vm, vm, 'unshift', arr_pro, namespace)
  arr.__proto__ = arr_pro
  return arr
}

/**
*对数组的方法进行代理
*@param {Hue} vm 创建的Hue实例
*@param {string} func 调用的方法名
*@param {Object} arr_pro 代理的对象
*@param {string} namespace 命名空间
*/
function defArrayFunc(vm, func, arr_pro, namespace) {
  Object.defineProperty(arr_pro, func, {
    configurable: true,
    value: function (...args) {
      console.log(getNameSpace(namespace, func))
      let result = arrayPrototype[func].apply(this, args)
      rebuild(vm, getNameSpace(namespace, ''))
      renderDate(vm, getNameSpace(namespace, ''))
      return result
    }
  })
}

/**
*得到命名空间值
*@param {string} nowNameSpace 当前的命名空间
*@param {string} key 访问属性名
*/
function getNameSpace(nowNameSpace, key) {
  if (nowNameSpace === '' || nowNameSpace === null) return key
  else if (key === '' || key === null) return nowNameSpace
  else return nowNameSpace + '.' + key
}

/**
*传入数据进行代理
*@param {Hue} vm 创建的Hue实例
*@param {Object} obj 代理的对象
*@param {string} namespace 命名空间
*@param {boolean} isVmProxy 是否给vm代理，默认为true
*/
export function constructProxy(vm, obj, namespace, isVmProxy = true) {
  let objectProxy = null
  if (obj instanceof Array) {
    objectProxy = new Array(obj.length)
    for (let i = 0; i < obj.length; i++) {
      if (obj[i] instanceof Array) {
        objectProxy[i] = constructProxy(vm, obj[i], namespace + `[${i}]`)
      } else if (obj[i] instanceof Object) {
        objectProxy[i] = creatObjProxy(vm, obj[i], namespace + `[${i}]`, isVmProxy)
      } else {
        // 无法检测到索引的改变
        objectProxy[i] = obj[i]
      }
    }
    objectProxy = creatArrayProxy(vm, obj, namespace)
  } else if (obj instanceof Object) {
    objectProxy = creatObjProxy(vm, obj, namespace, isVmProxy)
  } else {
    throw Error('传参错误！')
  }
  return objectProxy
}